...loading
2024-10-21
지난 포스팅에서 비동기 처리의 문제에 대해서 다뤘고, 이에 대한 해결 방안 중 하나로 콜백함수를 언급했다. 이번 포스팅에서는 이 콜백함수에 대해 다뤄보고자 한다. 내용은 다음과 같다. 콜백함수로 해당 문제를 어떻게 해결할 수 있는지, 그리고 __콜백지옥__이라는 콜백함수가 지닌 문제점이 무엇인가이다.
콜백함수란 매개변수로 전달되는 함수를 의미한다. "Hello world" 를 출력하는 함수를 콜백패턴으로 만들어보겠다.
const helloWorld = function(callback) { console.log(`Hello ${callback()}`); }; helloWorld(function () { return 'world' }); // Hello world
간단한 콜백패턴을 구현하였다.
'world'라는 문자열을 반환하는 익명함수를 helloWorld함수의 매개변수로 전달하였다. 이처럼 매개변수로 함수가 전달될 때, 그 함수를 콜백함수라 한다.
지난 포스팅에서 네트워크 통신의 비동기 처리 문제에 대해서 다뤘다. 해당 문제는 비동기 처리된 결과의 순차성을 보장할 수 없다는 것이다. 그렇다면 이를 어떻게 해소할 수 있을까? 만약 위에서 설명한 콜백패턴을 통해 하나의 비동기 처리가 완료된 후 다음 처리를 시작시키면 되지 않을까.
맞다, 매개변수로 다음의 비동기 처리 로직을 전달하게 만들면 개발자가 비동기 처리의 순서를 컨트롤할 수 있다!
지난 포스팅과 같은 예시를 들겠다. 서버에서 원하는 제목의 포스팅을 가져와 콘솔창에 출력하는 함수를 작성했다. A, B, C라는 제목의 포스팅을 순서대로 출력한다고 해보자. 이 경우 콜백함수를 매개변수에 전달함으로써, 비동기 처리되는 함수들의 반환 순서를 통제할 수 있다.
const getPosting = (title, callback) => { fetch(`www.myServer.com/postings`, { body : JSON.stringfy({ title: title }) }).then(res=> res.json()) .then(res => { console.log(res) callback ? callback() : null; }) } getPosting('A', () => { getPosting('B', () => { getPosting('C', () => { } } }
해당예시처럼 콜백패턴을 사용하면, 비동기 처리의 반환값을 관리해 줄 수 있다. 그런데, 문제가 있다.
. . . getPosting('A', () => { getPosting('B', () => { getPosting('C', () => { } } }
코드의 아래부분을 보면 알 수 있듯이 콜백을 중첩시킬수록 들여쓰기가 증가하고 코드가 복잡해질 것만 같다.
위와 같은 이유 때문에 코드가 매우 복잡해지는 문제를 __콜백지옥__이라 부른다. 위의 예시는 중첩이 몇번 이루어지지 않았지만, 중첩이 많다면 어떻게 될까.
말도 안되게 복잡해진다... 이 경우 전달되는 콜백함수가 어떠한 함수인지 알아보기도 힘들며 코드가 엉망이 된다.
이처럼 콜백함수를 남용하는 것은 부작용을 일으킨다. 그렇기에, 비동기 처리를 관리하기 위해 더 나은 대안이 있다. 바로 다음 포스팅에서 다루게 될 Promise 이다.
Comments